package Thread;

import java.util.PriorityQueue;
import java.util.concurrent.Executors;

//模拟实现定时器
//基于抽象类的方法定义,这样子虽然可以，但是写起来有一些麻烦
//abstract class MyTimeTask implements Runnable{
//    @Override
//    public abstract void run();
//}
//但是这样子有点麻烦，还有另外的写法
class MytimeTask implements Comparable<MytimeTask>{
    private Runnable task;
    //记录任务执行的时间
    private long time;
    public MytimeTask(Runnable task,long time){
        this.task=task;
        this.time=time;
    }
//需求是能够让时间最小的元素能够在队首（小根堆）
    @Override
    public int compareTo(MytimeTask o) {
        return (int)(this.time-o.time);
    }
    //获取时间
    public long getTime(){
        return time;
    }

    public void run() {
        task.run();
    }
}
class Mytime{
    private PriorityQueue<MytimeTask> queue=new PriorityQueue<>();

    private Object locker=new Object();
    public void schedule(Runnable task,long delay){
        synchronized (locker){
            //获取当前时刻的时间戳
            MytimeTask timeTask=new MytimeTask(task,System.currentTimeMillis()+delay);
            queue.offer(timeTask);
            locker.notify();
        }
    }
 public Mytime(){
      //创建一个线程，负责执行队列中的任务
     Thread t=new Thread(()->{
         try{
             while (true){
                 synchronized (locker){
                     //取出队首元素
                     //加上while循环,防止队列为空时，线程一直阻塞
                     while (queue.isEmpty()){
                         locker.wait();
//                     continue;
                     }
                     MytimeTask task=queue.peek();
                     if(task.getTime()>System.currentTimeMillis()){
                         //当前任务时间，如果比相同时间大，说明任务时机还没有到，继续等待
                        // continue;
                         locker.wait(task.getTime()-System.currentTimeMillis());
                     }else {
                         //时间到了，执行任务
                         task.run();
                         queue.poll();
                     }
                 }
             }
         }catch (InterruptedException e){
             e.printStackTrace();
         }

     });
     t.start();
 }

}

public class Dom35 {
    public static void main(String[] args) {
        Mytime timer=new Mytime();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("HELLO 3000");
            }
        },3000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("HELLO 2000");
            }
        },2000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("HELLO 1000");
            }
        },1000);
        //创建了一个带有线程池的定时器
        Executors.newScheduledThreadPool(4);
    }
}
